Source code for hysop.tools.interface

# Copyright (c) HySoP 2011-2024
#
# This file is part of HySoP software.
# See "https://particle_methods.gricad-pages.univ-grenoble-alpes.fr/hysop-doc/"
# for further info.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from abc import ABCMeta, abstractmethod
from hysop.tools.htypes import check_instance, first_not_None, to_tuple
from hysop.tools.numpywrappers import npw


[docs] class SymbolContainerI(metaclass=ABCMeta): def _get_symbol(self): """ Return a Symbol that can be used to compute symbolic expressions referring to this continuous field. """ assert hasattr(self, "_symbol"), "Symbol has not been defined." return self._symbol symbol = property(_get_symbol) s = property(_get_symbol)
[docs] class NamedObjectI(metaclass=ABCMeta):
[docs] def __new__(cls, name, pretty_name=None, latex_name=None, var_name=None, **kwds): """ Create an abstract named object that contains a symbolic value. name : string A name for the field. pretty_name: string, optional. A pretty name used for display whenever possible. Defaults to name. kwds: dict Keywords arguments for base class. """ obj = super().__new__(cls, **kwds) obj.rename( name=name, pretty_name=pretty_name, latex_name=latex_name, var_name=var_name ) return obj
def __init__(self, name, pretty_name=None, latex_name=None, var_name=None, **kwds): super().__init__(**kwds)
[docs] def rename(self, name, pretty_name=None, latex_name=None, var_name=None): """Change the names of this object.""" check_instance(name, str) check_instance(pretty_name, str, allow_none=True) check_instance(latex_name, str, allow_none=True) pretty_name = first_not_None(pretty_name, name) latex_name = first_not_None(latex_name, name) check_instance(pretty_name, str) self._name = name self._pretty_name = pretty_name self._latex_name = latex_name
def _get_name(self): """Return the name of this field.""" return self._name def _get_pretty_name(self): """Return the pretty name of this field.""" return self._pretty_name def _get_latex_name(self): """Return the latex name of this field.""" return self._latex_name def __str__(self): return self.long_description()
[docs] @abstractmethod def short_description(self): """Short description of this field as a string.""" pass
[docs] @abstractmethod def long_description(self): """Long description of this field as a string.""" pass
name = property(_get_name) pretty_name = property(_get_pretty_name) latex_name = property(_get_latex_name)
[docs] class NamedScalarContainerI(NamedObjectI, SymbolContainerI): @property def ndim(self): """Number of dimensions of this this tensor.""" return 0 def _get_var_name(self): """Return the variable name of this field.""" return self._var_name
[docs] def rename(self, name, pretty_name=None, latex_name=None, var_name=None): """Change the names of this object.""" super().rename(name=name, pretty_name=pretty_name, latex_name=latex_name) self.check_and_set_varname(first_not_None(var_name, self._name))
[docs] def check_and_set_varname(self, var_name): check_instance(var_name, str, allow_none=True) msg = f"Invalid variable name {var_name}." if var_name[0] in tuple(str(x) for x in range(10)): raise RuntimeError(msg) for c in "/*+-=|&()[]{}-!?:;,'\"#$^%<>@": if c in var_name: raise RuntimeError(msg) self._var_name = var_name
[docs] def nd_iter(self): """Return an nd-indexed iterator of contained objects.""" yield ((1,), self)
[docs] def __iter__(self): """Return an iterator on unique scalar objects.""" return (self,).__iter__()
[docs] def __tuple__(self): """ Fix hysop.tools/type.to_tuple for FieldContainers, because __iter__ has been redefined. """ return (self,)
[docs] def __contains__(self, obj): """Check if a scalar object is contained in self.""" return obj is self
def __getitem__(self, slc): return self var_name = property(_get_var_name)
[docs] class NamedTensorContainerI(NamedObjectI, SymbolContainerI): def __new__(cls, contained_objects, **kwds): check_instance(contained_objects, npw.ndarray) obj = super().__new__(cls, **kwds) obj._contained_objects = contained_objects return obj def __init__(self, contained_objects, **kwds): super().__init__(**kwds)
[docs] def rename(self, name, pretty_name=None, latex_name=None, var_name=None): """Change the names of this object.""" assert var_name is None, "Tensor do not have variable names." super().rename(name=name, pretty_name=pretty_name, latex_name=latex_name)
@property def size(self): """Full size of this container as if it was a 1D tensor.""" return self._contained_objects.size @property def shape(self): """Shape of this tensor.""" return self._contained_objects.shape @property def ndim(self): """Number of dimensions of this this tensor.""" return self._contained_objects.ndim
[docs] def new_empty_array(self, dtype=object): """Return a new empty array of the same shape as self.""" if dtype is object: array = npw.empty(shape=self.shape, dtype=dtype) array[...] = None else: array = npw.zeros(shape=self.shape, dtype=dtype) return array
[docs] def iter_fields(self): """Return an iterator on unique scalar object along with 1d index.""" yield from enumerate(self._contained_objects.ravel())
[docs] def nd_iter(self): """Return an nd-indexed iterator of contained objects.""" for idx in npw.ndindex(*self._contained_objects.shape): yield (idx, self._contained_objects[idx])
[docs] def __iter__(self): """Return an iterator on unique scalar objects.""" return self._contained_objects.ravel().__iter__()
[docs] def __tuple__(self): """ Fix hysop.tools/type.to_tuple for FieldContainers, because __iter__ has been redefined. """ return (self,)
[docs] def __contains__(self, obj): """Check if a scalar object is contained in self.""" return obj in self._contained_objects
@abstractmethod def __getitem__(self, slc): pass